% !TeX program = xelatex 
\documentclass[xcolor=svgnames,10pt,UTF8]{ctexbeamer}
%\documentclass[aspectratio=169,xcolor=svgnames,10pt]{beamer}

\RequirePackage{slide}

%\logo{\includegraphics[scale=0.015]{../figure/logo.jpg}}
\title{SystemVerilog芯片验证}
\subtitle{第8章~功能覆盖}
%\author{王旭}
%\institute{深圳信息职业技术学院~微电子学院}
\date{\today}

\begin{document}

\frame{\titlepage}
%\LogoOn
%\LogoOff

\begin{frame}[t,fragile]{}

\begin{figure}[!htb]
	\centering%\captionsetup{font={small}}\small
	\scalebox{0.8}{
		\begin{tikzpicture}
			\tikzstyle{every node}=[font=\normalsize]
			\node (crt) [align=left] {CRT};
			\node (seed) [thick,draw,align=left,right of=crt, xshift=2cm] {1. 更多种子\\多次测试};
			\node (constrain) [thick,draw,left of=crt, xshift=-1cm, yshift=-1.5cm] {2. 添加约束};
			\node (directed) [thick,draw,align=left,right of=constrain,xshift=2.5cm] {3. 定向测试};
			\node (coverage) [align=left,right of=directed,xshift=3cm] {分析功能\\覆盖率};
			\node (modify) [align=left,right of=constrain,xshift=2cm, yshift=-1.5cm] {最少量的\\代码修改};
			\node (blind) [thick,draw,align=left,right of=modify,xshift=1.5cm] {识别覆\\盖盲区};

			\draw [-Latex, thick] (constrain) to [out=90,in=180] (crt);
			\draw [-Latex, thick] (crt) to [out=0,in=180] (seed);
			\draw [-Latex, thick] (seed) to [out=0,in=90] (coverage);
			\draw [-Latex, thick] (coverage) to [out=270,in=0] (blind);
			\draw [-Latex, thick] (blind) to [out=180,in=0] (modify);
			\draw [-Latex, thick] (modify) to [out=180,in=270] (constrain);
			\draw [-Latex, thick, dotted] (modify) to [out=180,in=180] (directed);
			\draw [-Latex, thick, dotted] (directed) to [out=0,in=180] (coverage);
		\end{tikzpicture}
	}
	%\caption{覆盖收敛反馈环路} \label{ch09 Coverage convergence}
\end{figure}

\end{frame}

\section{覆盖类型} \label{Coverage Types}

\subsection{代码覆盖} \label{Code Coverage}

\begin{frame}[t,fragile]{代码覆盖}

\begin{enumerate}
	\item 行覆盖（line coverage）：即DUT的所有有效代码是否都被执行过（即覆盖）。
	\item 条件覆盖（condition coverage）：条件覆盖和分支覆盖很容易混淆，条件覆盖指可能进入某个分支的所有条件的组合都应该被遍历到。
	\item 状态机覆盖（FSM coverage）：即状态机里所有可能发生的状态跳转都要被遍历到。
	\item 分支覆盖（branch coverage）：即DUT的所有模块的每个条件分支是否有被执行过（包括if、else和case语句等）。
	\item 翻转覆盖（toggle coverage）：即DUT的每个模块的信号（包括端口信号和内部信号）是否有被翻转过（即每个信号都从0到1或从1到0变化过）。例如异步复位信号rst\_n只从0到1翻转过，但没有从1到0翻转过，那么这个信号没有被翻转覆盖。
	\item 断言覆盖（assertion coverage）：断言是用于监控信号在逻辑上或者时序上是否运行正确的声明性代码。断言覆盖就是统计测试平台中的所有断言是否被执行过。
\end{enumerate}

\end{frame}

\begin{frame}[t,fragile]{代码覆盖不能用来衡量验证计划的完成进度}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]
{src/ch8/sec1/1/dut.sv}

默认情况下测试平台不会收集代码覆盖。添加仿真选项“-cm line+cond+fsm+tgl+branch+assert”。

\end{frame}

\subsection{功能覆盖} \label{subsec Functional Coverage}

\section{覆盖组和覆盖点} \label{sec Anatomy of a Cover Group}

\begin{frame}[t,fragile]{覆盖组和覆盖点}

覆盖组是一种自定义类型，通常被定义在package、module、interface或class中。覆盖组在不同的环境下可以被例化多次。覆盖组和类相似，它必须使用new函数例化后才可以使用。覆盖组包含了覆盖模型的规范，一个覆盖组可以包含如下内容。

\begin{enumerate}
	\item 可选的触发条件。
	\item 一个或多个覆盖点。
	\item 覆盖点间的交叉覆盖。
	\item 可选的形式参数。
	\item 覆盖选项。
\end{enumerate}

\end{frame}

\subsection{模块中的覆盖组} \label{subsec Simple Functional Coverage Example}

\begin{frame}[t,fragile]{模块中的覆盖组}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-24},consecutivenumbers=false]
{src/ch8/sec2/1/test.sv}

\end{frame}

\begin{frame}[t,fragile]{提高功能覆盖率最简单的方法是发送更多的随机事务}

\begin{lstlisting}
Tests
Total Coverage Summary 
SCORE  GROUP  
 81.25  81.25 
Total tests in report: 1
\end{lstlisting}

\end{frame}

\subsection{类中的覆盖组} \label{Defining a Cover Group in a Class}

\begin{frame}[t,fragile]{类中的覆盖组}

类中定义的覆盖组只能在构造方法中创建，而非嵌入式覆盖组可以在运行过程中的任意时间创建。嵌入式覆盖组可以直接使用，不需要定义覆盖组句柄。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-4,8-24},consecutivenumbers=false]
{src/ch8/sec2/2/sequencer.svh}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={7-14},consecutivenumbers=false]
{src/ch8/sec2/2/test.sv}

\end{frame}

\subsection{条件覆盖} \label{Conditional Coverage}

\begin{frame}[t,fragile]{条件覆盖}

使用关键字iff可以向覆盖点添加执行条件，常用于复位期间关闭覆盖点。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={7-7,10-26},consecutivenumbers=false]
{src/ch8/sec2/3/test.sv}

\end{frame}

\section{覆盖组的触发} \label{Triggering a Cover Group}

\begin{frame}[t,fragile]{覆盖组的触发}

功能覆盖的主要内容包括采样数据和采样触发条件。当新数据准备好时（例如发送完一个事务），测试平台便会触发覆盖组。触发覆盖组的主要方式如下。

\begin{enumerate}
	\item 如果代码中不存在标识何时采样的信号或事件，或者一个覆盖组中有多个实例需要独立触发，这时应该使用sample方法显式触发覆盖。
	\item 如果想借助已有事件或信号来触发覆盖，可以在覆盖组中使用覆盖事件。覆盖事件使用“@”操作符阻塞信号或事件。
\end{enumerate}

\end{frame}

\subsection{使用sample方法触发覆盖组} \label{Cover Group with a User Defined Sample Argument List}

\begin{frame}[t,fragile]{使用sample方法触发覆盖组}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-24},consecutivenumbers=false]
{src/ch8/sec3/1/sequencer.svh}

\end{frame}

\subsection{使用事件触发覆盖组} \label{Cover Group with an Event Trigger}

\begin{frame}[t,fragile]{使用事件触发覆盖组}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-4,7-25},consecutivenumbers=false]
{src/ch8/sec3/2/sequencer.svh}

\end{frame}

\subsection{使用断言触发覆盖组} \label{Triggering on a SystemVerilog Assertion}

\begin{frame}[t,fragile]{使用断言触发覆盖组}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={9-29},consecutivenumbers=false]
{src/ch8/sec3/3/test.sv}

\end{frame}

\section{仓} \label{Data Sampling}

\subsection{创建仓} \label{Naming the Cover Point Bins}

\begin{frame}[t,fragile]{创建仓}

关键字bins用于在覆盖点中创建一个或多个仓。

\begin{enumerate}
	\item 单独使用bins可以创建一个仓，例子中仓zero包含数值0。
	\item 使用bins加方括号[N]可以创建N个仓。例子中bins lo[3]会创建3个仓。
	\item 使用bins加空方括号[]可以为每个采样值创建一个仓。例子中bins hi[]会创建8个仓，用于记录采样值[8:15]的命中次数。“\$”在范围表达式中表示取值范围上限。
	\item 使用关键字default定义独立的默认仓misc，它不参与覆盖率的计算，默认仓在捕获未计划的或无效的值时非常有用。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-16},consecutivenumbers=false]
{src/ch8/sec4/1/sequencer.svh}

\end{frame}

\subsection{通用覆盖组} \label{Generic Coverage Groups}

\begin{frame}[t,fragile]{通用覆盖组}

定义一个通用覆盖组（generic coverage group），然后在例化时指定被采样的变量和相应的覆盖特性。通用覆盖组属于非嵌入式覆盖组，它可以在运行过程中的任意时间创建。

通用覆盖组cg使用引用的方式指定被采样的变量，采用值传递的方式指定其他参数。在方法main中创建覆盖组实例cga和cgb对随机属性a和b进行采样，即使用通用覆盖组中的同一个覆盖点对多个随机属性采样。覆盖组中设置覆盖实例选项option.per\_instance为1，这样各个覆盖组实例的覆盖率会被分开统计。如果不设置该选项，则覆盖组的所有实例会被叠加在一起进行统计。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-11},consecutivenumbers=false]
{src/ch8/sec4/2/sequencer.svh}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={13-29},consecutivenumbers=false]
{src/ch8/sec4/2/sequencer.svh}

\end{frame}

\subsection{表达式的采样} \label{Sampling Expressions}

\begin{frame}[t,fragile]{表达式的采样}

在覆盖点中使用表达式时要留意结果的数据位宽对仓的影响。

\begin{enumerate}
	\item 在覆盖点sum1中使用关键字bins定义31个仓，排除掉数值31。
	\item 在覆盖点sum2中使用with语句约束bins选择小于31的所有值。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-13},consecutivenumbers=false]
{src/ch8/sec4/3/sequencer.svh}

自动生成的仓适用于匿名数据值，如计数值、地址值或2的幂值。

对于重要的数据值，应该使用有名字的仓以提高准确度并易于覆盖报告的分析。

\end{frame}

\subsection{限制仓的个数} \label{Limiting the Number of Automatic Bins Created}

\begin{frame}[t,fragile]{限制仓的个数}

覆盖实例选项option的成员auto\_bin\_max用于手动设置仓的最大数目，它的默认值是64。如果覆盖点的可能取值个数大于auto\_bin\_max，仿真器会将可能取值平均分配给每个仓。

在覆盖点中设置auto\_bin\_max等于2，则该覆盖点中属性a的16个可能取值被平均分配在两个仓中，其中第一个仓包含数值0\textasciitilde7，第二个仓包含数值8\textasciitilde15。如果在仿真过程中只采样到数值1，则第一个仓被覆盖，这时这个覆盖点的覆盖率是50\%。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-10},consecutivenumbers=false]
{src/ch8/sec4/4/sequencer.svh}

在覆盖组中设置auto\_bin\_max后，它将作用于覆盖组中的所有覆盖点，

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-11},consecutivenumbers=false]
{src/ch8/sec4/5/sequencer.svh}

\end{frame}

\subsection{创建忽略仓和非法仓} \label{Ignoring Values}

\begin{frame}[t,fragile]{创建忽略仓和非法仓}

	\begin{enumerate}
		\item 在覆盖点的附加信息中使用ignore\_bins创建忽略仓，忽略仓不参与覆盖率的计算。
		\item 有些采样值应该被忽略，并且如果出现还应该报错，这时应该使用illegal\_bins对仓进行标识。
	\end{enumerate}

	\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-19},consecutivenumbers=false]
{src/ch8/sec4/6/sequencer.svh}

\end{frame}

\subsection{枚举变量与仓} \label{Creating Bins for Enumerated Types}

\begin{frame}[t,fragile]{枚举变量与仓}

收集枚举变量的覆盖时，枚举变量的每个枚举值都对应一个仓，且选项auto\_bin\_max不起作用。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
typedef enum {IDLE, INIT, DECODE} fsmstate_e;
fsmstate_e pstate, nstate;

covergroup state_cg;
	coverpoint pstate;
endgroup
\end{lstlisting}

\end{frame}

\subsection{转换覆盖} \label{Transition Coverage}

\begin{frame}[t,fragile]{转换覆盖}

覆盖点中还可以指定变量的数值转换。例子中第一个bins结构用来查询属性a是否从0变为1、2或3，对应3个转换仓。第二个bins结构使用表达式(0, 2 => 1, 3)创建了4个转换过程，分别是(0 => 1)、(0 => 3)、(2 => 1)和(2 => 3)，对应4个转换仓。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-14},consecutivenumbers=false]
{src/ch8/sec4/7/sequencer.svh}

转换覆盖中对转换长度没有限定，但是转换过程中每个状态只能被采样一次。例如(0 => 1 => 2)与(0 => 1 => 1 => 2)并不等价。后者状态1需要被重复采样两次，也可以使用缩略形式(0 => 1[*2] => 2)代替。如果需要对数值1重复采样3、4或5次，可以使用(0 => 1[*3:5] => 2)。

\end{frame}

\subsection{通配符仓} \label{Wildcard States and Transitions}

\begin{frame}[t,fragile]{通配符仓}

	使用关键字wildcard可以创建通配符仓。在表达式中任何x、z或?都会被当成0或1的通配符。覆盖点track\_a创建了两个仓，一个仓包含全部的偶数值，另一个仓包含全部的奇数值。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-14},consecutivenumbers=false]
{src/ch8/sec4/8/sequencer.svh}

\end{frame}

\section{交叉覆盖} \label{Cross Coverage}

\subsection{建立交叉覆盖} \label{Basic Cross Coverage Example}

\begin{frame}[t,fragile]{建立交叉覆盖}

	交叉覆盖用于同时测量两个或多个覆盖点的可能值。

	cross结构用来记录一个覆盖组中两个或两个以上覆盖点的组合值。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-12},consecutivenumbers=false]
{src/ch8/sec5/1/sequencer.svh}

\end{frame}

\subsection{binsof和intersect结构} \label{Excluding Cross Coverage Bins}

\begin{frame}[t,fragile]{binsof和intersect结构}

cross结构只能操作简单的覆盖点，更精细的交叉覆盖操作应该围绕覆盖点中的仓展开。假设测试平台要采样事务类中属性a和b的3种组合状态，分别是(a==0, b==0)、(a==1, b==0)和(b==1)。首先应该在覆盖点中为这些感兴趣的数值创建对应的仓，覆盖点track\_a中创建了仓a0和a1，覆盖点track\_b中创建了仓b0和b1。
\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-20},consecutivenumbers=false]
{src/ch8/sec5/2/sequencer.svh}

\end{frame}

\begin{frame}[t,fragile]{}

接下来在交叉覆盖中使用binsof结构生成3个新的交叉仓a0b0、a1b0和b1，现在使用这些交叉仓就可以收集到想要的功能覆盖率。注意binsof结构使用的表达式应该是一个覆盖点或一个仓。例子中将覆盖点的权重设置为0，它们不参与覆盖组实例的功能覆盖率计算。
	
	\lstinputlisting[language=SystemVerilog,numbers=left,linerange={21-27},consecutivenumbers=false]
	{src/ch8/sec5/2/sequencer.svh}
	
\end{frame}

\begin{frame}[t,fragile]{binsof结构可以和intersect结构配合使用}

binsof结构可以和intersect结构配合使用，后者用来设置覆盖点的数值子集，即binsof结构生成的仓可以使用intersect进行二次筛选或排除。注意binsof结构使用的是小括号()，而intersect结构使用大括号\{\}指定一个取值范围。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-17},consecutivenumbers=false]
{src/ch8/sec5/3/sequencer.svh}

\end{frame}

\begin{frame}[t,fragile]{}

	交叉覆盖产生了4个交叉仓，分别是<a0,b0>、<a0,b1>、<a1,b0>和<a1,b2>。在交叉仓c0中，指定c0不包括覆盖点track\_a中取值大于5的仓，这个选择表达式排除了仓a1。因此c0只包含<a0,b0>和<a0,b1>。在交叉仓c1中，指定c1包括仓a0或b1。因此c1包括<a0,b0>、<a0,b1>和<a1,b1>，排除了<a1,b0>。在交叉仓c2中，指定c2只包括仓a0和b1。因此c2只包括<a0,b1>。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-20},consecutivenumbers=false]
{src/ch8/sec5/4/sequencer.svh}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={21-27},consecutivenumbers=false]
{src/ch8/sec5/4/sequencer.svh}

\end{frame}

\begin{frame}[t,fragile]{ignore\_bins结构和binsof结构}

忽略仓ignore0排除覆盖点track\_b中采样值等于7的仓。忽略仓ignore1排除覆盖点track\_a中采样值介于[9:11]且覆盖点track\_b中采样值等于0的仓。ignore\_bins还可以使用覆盖点中已经定义的仓。忽略仓ignore2排除了仓lo。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-23},consecutivenumbers=false]
{src/ch8/sec5/5/sequencer.svh}

\end{frame}

\section{覆盖选项} \label{Coverage Options}

\begin{frame}[t,fragile]{覆盖选项}

覆盖选项用来控制覆盖组、覆盖点和交叉覆盖的行为。覆盖选项主要包括两类：

\begin{enumerate}
	\item 实例选项（instance option）：每个覆盖组实例及其内部的覆盖点和交叉覆盖都内置了自动类型的option，用于控制当前覆盖组实例。
	\item 类型选项（type option）：覆盖组、覆盖点和交叉覆盖都内置了静态类型的type\_option，用来控制整个覆盖组。
\end{enumerate}

\end{frame}

\subsection{实例选项} \label{Specifying coverage options}

\begin{frame}[t,fragile]{实例选项}

实例选项option在覆盖组实例的不同层级包含不同的选项名。在覆盖组实例中，一些高层级的选项名会影响低层级的同名选项名，例如覆盖组实例层级的选项名option.at\_least会影响其内部各个覆盖点和交叉覆盖的option.at\_least。

\begin{table}[!htb]
	\centering%\captionsetup{font={small}}\small %small or scriptsize
	%\caption{实例选项option包含的选项名} \label{Coverage options per syntactic level}%
	\begin{tabular}{llll}
		\hline
		\rowcolor{black!10}选项名     & 覆盖组实例    & 覆盖点 & 交叉覆盖 \\\hline
		name                       & 有        & 无   & 无    \\\hline
		weight                     & 有        & 有   & 有    \\\hline
		goal                       & 有        & 有   & 有    \\\hline
		comment                    & 有        & 有   & 有    \\\hline
		at\_least                  & 有（影响低层级） & 有   & 有    \\\hline
		auto\_bin\_max             & 有（影响低层级） & 有   & 无    \\\hline
		cross\_num\_print\_missing & 有（影响低层级） & 无   & 有    \\\hline
		detect\_overlap            & 有（影响低层级） & 有   & 无    \\\hline
		per\_instance              & 有        & 无   & 无    \\\hline
		get\_inst\_coverage        & 有        & 无   & 无    \\\hline
	\end{tabular}%
\end{table}

\end{frame}

\begin{frame}[t,fragile]{实例选项说明}

在覆盖组实例层级，option的各个选项名的含义如下。

\begin{enumerate}
	\item name：设置覆盖组实例的名字，如果不设置该选项名，编译器会自动为每个实例生成不重复的名字。
	\item weight：设置覆盖组实例及其内部各个层级的权重值，默认值为1。
	\item goal：设置覆盖组实例及其内部各个层级的目标覆盖率，注意该选项只影响覆盖率报告，默认值为100。
	\item comment：设置覆盖组实例及其内部各个层级的注释，这些注释最终会出现在覆盖率报告中。
	\item at\_least：设置覆盖组实例内部各个仓的最小命中次数，默认值为1。当仓中数值被采样到的次数大于等于at\_least时，就认为这个仓被命中。
	\item auto\_bin\_max：设置覆盖组实例内部各个仓的最大个数，默认值为64。
\end{enumerate}

\end{frame}

\begin{frame}[t,fragile]{实例选项说明}

\begin{enumerate}
	\item cross\_num\_print\_missing：设置保存在覆盖数据库并打印在覆盖率报告中的未被命中的交叉覆盖仓的数量。
	\item detect\_overlap：当一个覆盖点的两个仓的取值或转换列表出现重叠时输出警告信息，默认值为0表示不输出警告信息。
	\item per\_instance：在测试平台中通用覆盖组可能被例化多次，默认情况下所有覆盖组实例的覆盖信息会被汇集到一起，从而生成一个整体覆盖报告。如果需要查看单个覆盖组实例的报告，需要将选项名per\_instance设置为1。
	\item get\_inst\_coverage：目前大多数主流编译器暂不支持这个选项名。
\end{enumerate}

\end{frame}

\subsection{类型选项} \label{Specifying type option}

\begin{frame}[t,fragile]{类型选项}

	每个覆盖组、覆盖点和交叉覆盖都内置了静态类型的类型选项type\_option，它内部常用的成员包括weight、goal、comment、strobe和merge\_instances，它们的含义如下。

\begin{enumerate}
	\item weight：设置覆盖组/覆盖点/交叉覆盖的权重值，默认值为1。
	\item goal：设置覆盖组/覆盖点/交叉覆盖的目标覆盖率，这个选项只影响覆盖率报告，默认值为100。
	\item comment：为覆盖组/覆盖点/交叉覆盖添加注释内容，这些注释最终会出现在覆盖率报告中。
	\item strobe：设置为1时在每个时间片的最后时刻采样。默认值为0。
	\item merge\_instances：设置为1将所有覆盖组实例的覆盖信息合并到类型覆盖信息中。默认值为0。
\end{enumerate}

\end{frame}

\subsection{功能覆盖率与权重} \label{Excluding Cover Points from the Total Coverage Metric}

\begin{frame}[t,fragile]{功能覆盖率与权重}

覆盖组的功能覆盖率分为两种，第一种是累积（类型）覆盖率，它的结果由覆盖组的所有实例和type\_option.weight共同决定。第二种是实例覆盖率，它的结果由当前覆盖组实例和option.weight决定。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-16},consecutivenumbers=false]
{src/ch8/sec6/1/sequencer.svh}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={17-36},consecutivenumbers=false]
{src/ch8/sec6/1/sequencer.svh}

\end{frame}

\begin{frame}[t,fragile]{}

	\lstinputlisting[language=SystemVerilog,numbers=left,linerange={38-50},consecutivenumbers=false]
	{src/ch8/sec6/1/sequencer.svh}
	
	\end{frame}

\begin{frame}[t,fragile]{功能覆盖率与权重}

sequencer类的main方法将transaction对象随机化8次并采样。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={7-14},consecutivenumbers=false]
{src/ch8/sec6/1/test.sv}

\end{frame}

\begin{frame}[t,fragile]{功能覆盖率与权重}

在sequencer的main方法中调用覆盖组的内置方法get\_inst\_coverage获取覆盖组的实例覆盖率，调用内置方法get\_coverage获取覆盖组的类型覆盖率。系统函数\$get\_coverage用来获取测试平台的功能覆盖率。因为DUT中只包含一个覆盖组，所以覆盖组的类型覆盖率等于测试平台的功能覆盖率。

\begin{lstlisting}
sequencer: a=9, b=12
sequencer: a=11, b=0
sequencer: a=10, b=6
sequencer: a=7, b=2
sequencer: a=0, b=12
sequencer: a=3, b=6
sequencer: a=10, b=12
sequencer: a=3, b=14
instance coverage=33.750000
type coverage=33.593750
total coverage=33.593750
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{功能覆盖率与权重}

从测试结果可以看出，属性a产生了6个不重复的取值，覆盖点track\_a的覆盖率为37.5\%，属性b产生了5个不重复的取值，覆盖点track\_b的覆盖率为31.25\%。覆盖组cg的实例覆盖率计算公式如下。

\begin{equation}\label{cmpute inst coverage}
	{C_g} = \frac{{\sum\limits_i {{W_i} \times {C_i}} }}{{\sum\limits_i {{W_i}} }} = \frac{{2 \times 37.5\%  + 3 \times 31.25\% }}{{2 + 3}} = 33.75\%
\end{equation}

其中$i$表示覆盖组中的覆盖子项（覆盖点或交叉覆盖），${W_i}$表示覆盖子项$i$的权重option.weight，${C_i}$表示覆盖子项$i$的覆盖率。

覆盖组cg的类型覆盖率$C_t$的计算公式如下。

\begin{equation}\label{cmpute type coverage}
	{C_t} = \frac{{\sum\limits_i {{W_i} \times {I_i}} }}{{\sum\limits_i {{W_i}} }} = \frac{{3 \times 37.5\%  + 5 \times 31.25\% }}{{3 + 5}} \approx 33.59375\%
\end{equation}

其中${W_i}$表示覆盖点的权重type\_option.weight，${I_i}$表示覆盖子项$i$的所有实例经过合并后得到的总覆盖率，因为测试平台中覆盖组只被例化了一次，所以${I_i}$等于${C_i}$。

\end{frame}

\subsection{覆盖组的注释} \label{Cover Group Comment}

\begin{frame}[t,fragile]{覆盖组的注释}

使用选项名comment可以在覆盖报告中添加注释，解析器通过注释内容从覆盖报告的海量数据中提取相关信息。如果覆盖组被例化多次，就应该使用实例选项为每个覆盖组实例加入单独的注释，前提是必须设置覆盖组的per\_instance选项为1。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
covergroup cg (ref bit [3:0] a, input int mid, input string comment);
	coverpoint a {
		bins lo = { [0:mid-1] };
		bins hi = { [mid:$] }; }
	option.per_instance = 1;
	option.comment = comment;
endgroup

cga = new(tr.a, 7, "tr.a");
cgb = new(tr.b, 9, "tr.b");
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{}

如果覆盖组只被例化一次，那么可以使用类型选项设置注释内容。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
covergroup cg;
	type_option.comment = "tr.a";
	coverpoint tr.a;
endgroup
\end{lstlisting}

\end{frame}

\subsection{打印未被覆盖的交叉仓} \label{Printing the Empty Bins}

\begin{frame}[t,fragile]{打印未被覆盖的交叉仓}

默认情况下，覆盖报告只会给出带有采样值的仓。但验证的目的是检查所有情况是否都被覆盖，所以查看那些未被命中的仓更有意义。设置选项cross\_num\_print\_missing可以将那些未被命中的交叉仓保存在覆盖数据库并打印在覆盖率报告中。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
covergroup cg;
	track_a: coverpoint tr.a;
	track_b: coverpoint tr.b;
	cross track_a, track_b;
	option.cross_num_print_missing = 50;
endgroup
\end{lstlisting}

\end{frame}

\subsection{覆盖目标} \label{Coverage Goal}

\begin{frame}[t,fragile]{覆盖目标}

认定一个覆盖组或覆盖点已经被完整覆盖的百分比例被称为覆盖目标，默认的覆盖目标为100\%。如果将覆盖目标设置为90\%，就意味着覆盖目标并不是真正的完整覆盖。覆盖目标选项只影响覆盖报告结果。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
covergroup cg;
	track_a: coverpoint tr.a;
	option.goal = 90; // 指定覆盖目标
endgroup
\end{lstlisting}

\end{frame}

\section{覆盖率数据分析} \label{Analyzing Coverage Data}

\begin{frame}[t,fragile]{覆盖率数据分析}

在实际的项目中，通常会使用更多的种子运行测试，而不是添加更多的约束，因为新约束很容易影响随机值的概率分布。

如果覆盖点命中数很低，说明约束可能根本就没有瞄准这些区域，这时需要增加约束将约束解析器调整到新区域中。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-16},consecutivenumbers=false]
{src/ch8/sec7/1/transaction.svh}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-27},consecutivenumbers=false]
{src/ch8/sec7/1/sequencer.svh}

\end{frame}

\begin{frame}[t,fragile]{覆盖率数据分析}

在测试模块中将num\_trans设置为20000，经过20000次采样后，可以看到sum采样值的命中次数分布并不均匀，较小值和较大值的命中次数很少，中间值命中次数最多。原因在于约束track\_sum，约束中按照随机属性\{a, b\}的组合计算sum采样值的概率分布。

\begin{figure}[!htb]
	\centering
	\includegraphics[scale=0.5]{uneven_dist.pdf}
	%\caption{sum采样值的命中次数不均匀分布} \label{Uneven probability for packet length}
\end{figure}

\end{frame}

\begin{frame}[t,fragile]{覆盖率数据分析}

如果想让sum各个采样值的命中次数趋于均匀分布，可以添加solve before约束。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-12},consecutivenumbers=false]
{src/ch8/sec7/2/transaction.svh}

也可以使用dist操作符让sum各个采样值的权重相等。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={8-12},consecutivenumbers=false]
{src/ch8/sec7/3/transaction.svh}

\end{frame}

\begin{frame}[t,fragile]{覆盖率数据分析}

重新运行测试后，可以看到sum各个采样值的命中次数趋于均匀分布。

\begin{figure}[!htb]
	\centering
	\includegraphics[scale=0.5]{even_dist.pdf}
	%\caption{使用solve before或dist让sum采样值的命中次数均匀分布} \label{Even probability for packet length with solve before}
\end{figure}

\end{frame}

\end{document}
